package data.news;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * "String... key" here refers to <key attr=val...> word ...
 * @author weeny
 *
 */
public class KeywordIterator implements Iterator<Keyword>{
	private BufferedReader reader = null;
	private String nodeKey = null;
	private Pattern pattern = null;
	public KeywordIterator(InputStream input, String... tagNames) {
		reader = new BufferedReader(new InputStreamReader(input));
		initPattern(tagNames);
	}
	
	public KeywordIterator(BufferedReader reader, String... tagNames){
		this.reader = reader;
		initPattern(tagNames);
	}
	public KeywordIterator(String input, String... tagNames){
		reader = new BufferedReader(new StringReader(input));
		scanForArticleID = false;
		initPattern(tagNames);
	}
	private void initPattern(String[] keys){
		String tmp = "";
		for(int i =0 ; i<keys.length-1; i++){
			tmp+=keys[i]+"|";
		}
		tmp+=keys[keys.length-1];
		this.nodeKey = tmp;
		this.pattern = Pattern.compile(".*?(<("+tmp+") *.*? *> .*? </("+tmp+")>)(.*)");
	}

	private String currentLine = null;
	private int nextIdx = 0;
	private Matcher currentLineMatcher = null;
	
	String nextNodeString = null;
	private Long currentArticleID = null;
	public void setCurrentArticleID(Long id){
		currentArticleID = id;
	}
	private boolean scanForArticleID = true;
	private boolean nextMatchedLine(){
		try {
			while((currentLine = reader.readLine())!=null){
				if (scanForArticleID && currentLine.contains("</article>")) {
					setCurrentArticleID(null);
				}
				if (scanForArticleID && currentLine.contains("<article ")) {
					setCurrentArticleID(new Long(ArticleIterator.getArticleID(currentLine)));
				}
				currentLineMatcher = pattern.matcher(currentLine);
				if (currentLineMatcher.find(0)) {
					nextIdx = currentLineMatcher.end(1);
					return true;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	public String getKey(){
		return nodeKey;
	}
	
	public boolean hasNext() {
		if (nextNodeString != null) {
			return true;
		}
		if (currentLine == null) {
			boolean result =  nextMatchedLine();
			if (result) {
				nextNodeString = currentLineMatcher.group(1);
			}
			return result;
		}
		else{
			if (currentLineMatcher.find(nextIdx)) {
				nextIdx = currentLineMatcher.end(1);
				nextNodeString = currentLineMatcher.group(1);
				return true;
			}
			else{
				boolean result =  nextMatchedLine();
				if (result) {
					nextNodeString = currentLineMatcher.group(1);
				}
				return result;
			}
		}
	}

	public Keyword next() {
		if (nextNodeString == null) {
			hasNext();
		}
		Keyword result =  new Keyword(nextNodeString, currentArticleID == null? -1 : currentArticleID.longValue());
		nextNodeString = null;
		return result;
	}

	public void remove() {
		throw new UnsupportedOperationException();
	}
}
